import axios, { RawAxiosRequestHeaders, AxiosResponse } from 'axios';
import { getToken, removeToken } from '@/common/utils';
import { createStandaloneToast } from '@chakra-ui/toast';

const { toast } = createStandaloneToast();

const unAuthorizedStatus = [401];
const nonValidatedRoutes = [
  '/',
  '/signin',
  '/autoAuth',
  '/registry',
  '/forgotPassword',
  '/404',
];

const validateRouteCheck = (route: string): boolean => {
  let validationToggle = false;

  let routeCheck = false;
  nonValidatedRoutes.forEach((_route: string) => {
    if (route.includes(_route)) {
      routeCheck = true;
    }
  });

  if (routeCheck) {
    validationToggle = true;
  }
  return validationToggle;
};

axios.interceptors.response.use(
  (response) => {
    const data = response.data;
    if (data?.code !== 200) {
      toast({
        position: 'top',
        description: data?.msg || '系统异常，请稍候再试！',
        status: 'error',
        duration: 5000,
        isClosable: true,
      });
    }
    return response;
  },
  (error) => {
    const { status }: AxiosResponse = error.response;
    if (!validateRouteCheck(window.location.pathname)) {
      if (unAuthorizedStatus.includes(status)) {
        removeToken();
        toast({
          position: 'top',
          description: '登录已过期，请重新登录',
          status: 'error',
          duration: 5000,
          isClosable: true,
        });
        window.location.href = '/signin';
      }
    }
    return Promise.reject(error);
  }
);

abstract class APIService {
  protected baseURL: string | undefined;
  protected headers: RawAxiosRequestHeaders = {};

  constructor(baseURL: string | undefined) {
    this.baseURL = baseURL ?? '';
  }

  getAccessToken() {
    return getToken();
  }

  getHeaders() {
    return {
      Authorization: `Bearer ${this.getAccessToken()}`,
    };
  }

  getWithoutBase(url: string, config = {}): Promise<any> {
    return axios({
      method: 'get',
      url: url,
      headers: this.getAccessToken() ? this.getHeaders() : {},
      ...config,
    });
  }

  get(url: string, config = {}): Promise<any> {
    return axios({
      method: 'get',
      url: this.baseURL + url,
      headers: this.getAccessToken() ? this.getHeaders() : {},
      ...config,
    });
  }

  post(url: string, data = {}, config = {}): Promise<any> {
    return axios({
      method: 'post',
      url: this.baseURL + url,
      data,
      headers: this.getAccessToken() ? this.getHeaders() : {},
      ...config,
    });
  }

  put(url: string, data = {}, config = {}): Promise<any> {
    return axios({
      method: 'put',
      url: this.baseURL + url,
      data,
      headers: this.getAccessToken() ? this.getHeaders() : {},
      ...config,
    });
  }

  patch(url: string, data = {}, config = {}): Promise<any> {
    return axios({
      method: 'patch',
      url: this.baseURL + url,
      data,
      headers: this.getAccessToken() ? this.getHeaders() : {},
      ...config,
    });
  }

  delete(url: string, data?: any, config = {}): Promise<any> {
    return axios({
      method: 'delete',
      url: this.baseURL + url,
      data: data,
      headers: this.getAccessToken() ? this.getHeaders() : {},
      ...config,
    });
  }

  mediaUpload(url: string, data = {}, config = {}): Promise<any> {
    return axios({
      method: 'post',
      url: this.baseURL + url,
      data,
      headers: this.getAccessToken()
        ? { ...this.getHeaders(), 'Content-Type': 'multipart/form-data' }
        : {},
      ...config,
    });
  }

  request(config = {}) {
    return axios(config);
  }
}

export default APIService;
